package twi.result.graph;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import twi.result.table.RTable;

import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.impl.LiteralImpl;

public class RGraph {

	public static final int EDGE = 12;
	public static final int NODE = 13;
	public static final int NODE_IGNOE = 14;
	public static final int NODE_TEMPORAERY = 15;
	public static final int ROOT_NODE = 16;
	public static final int NODE_CLASS_TEMPORAERY = 17;
	public static final int NODE_INDIVIDUAL_TEMP = 18;

	private HashMap<String, RNode> nodeMap = new HashMap<String, RNode>();
	private HashMap<String, REdge> edgeMap = new HashMap<String, REdge>();
	private HashMap<String, Integer> edgeTypes = new HashMap<String, Integer>();
	private HashMap<Integer, ArrayList<REdge>> edgeTypeMape = new HashMap<Integer, ArrayList<REdge>>();

	RNode root = null;
	
	public RGraph() {

	}

	public RNode addNode(RDFNode in) {
		String name = RTable.getNodeName(in);
		if (nodeMap.containsKey(name))
			return nodeMap.get(name);
		RNode node = new RNode(in);
		nodeMap.put(name, node);
		return node;
	}

	public void removeRootFromMap(){
		if (nodeMap.containsKey("root"))
			this.nodeMap.remove("root");
	}
	
	public REdge addEdge(RDFNode in, RDFNode out) {
		return addEdge(new RNode(in), new RNode(out));
	}

	public REdge addEdge(RNode o, RNode t, String etype) {
		return addEdge(null, o, t, etype);
	}

	public REdge addEdge(String name, RNode o, RNode t, String etype) {
		if (o == null || t == null)
			return null;
		if (o == t)
			return null;
		if (name == null)
			name = createEdgeName(o, t);
		if (edgeMap.containsKey(name))
			return edgeMap.get(name);
		int type = createNodeType(etype);
		REdge e = new REdge(name, o, t, type);
		if (!this.edgeTypeMape.containsKey(type))
			this.edgeTypeMape.put(type, new ArrayList<REdge>());

		edgeMap.put(name, e);
		this.edgeTypeMape.get(type).add(e);
		o.addOutNode(e);
		t.addInNode(e);
		return e;
	}

	private static int counter = 55;

	private int createNodeType(String etype) {
		if (etype == null)
			etype = "null";
		Integer i = this.edgeTypes.get(etype);
		if (i != null)
			return i.intValue();
		i = new Integer(counter++);
		this.edgeTypes.put(etype, i);
		return i.intValue();
	}

	public REdge addEdge(RNode o, RNode t) {
		return addEdge(null, o, t, null);
	}

	private String createEdgeName(RNode o, RNode t) {
		return o.getName() + "->" + t.getName();
	}

	public Iterator<RNode> getNodeIter() {
		return this.nodeMap.values().iterator();
	}

	public Iterator<REdge> getEdgeIter() {
		return this.edgeMap.values().iterator();
	}

	public void addNode(RNode origin) {
		if (!this.nodeMap.containsKey(origin.getName()))
			this.nodeMap.put(origin.getName(), origin);
	}

	public RNode addNode(String string) {
		RDFNode n = new LiteralImpl(string);
		return addNode(n);
	}

}
